home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 37
/
Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso
/
Aminet
/
dev
/
lang
/
sofa.lha
/
sofa
/
smalleiffel
/
lib_se
/
conversion_handler.e
< prev
next >
Wrap
Text File
|
2000-03-25
|
13KB
|
394 lines
-- This file is part of SmallEiffel The GNU Eiffel Compiler.
-- Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
-- Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
-- http://SmallEiffel.loria.fr
-- SmallEiffel is free software; you can redistribute it and/or modify it
-- under the terms of the GNU General Public License as published by the Free
-- Software Foundation; either version 2, or (at your option) any later
-- version. SmallEiffel is distributed in the hope that it will be useful,but
-- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for more details. You should have received a copy of the GNU General
-- Public License along with SmallEiffel; see the file COPYING. If not,
-- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-- Boston, MA 02111-1307, USA.
--
class CONVERSION_HANDLER
--
-- Singleton object used to handle allowed automatic conversion from
-- Eiffel type to another Eiffel type.
-- This singleton is shared via the GLOBALS.`conversion_handler' once function.
--
inherit GLOBALS;
feature
implicit_cast(expression: EXPRESSION; destination_type: TYPE): EXPRESSION is
-- If necessary, wrap `expression' inside an IMPLICIT_CAST invisible
-- wrapper object.
require
expression.result_type.is_a(destination_type)
local
source_bit, destination_bit: TYPE_BIT;
do
source := expression.result_type
if source.run_time_mark = destination_type.run_time_mark then
Result := expression;
elseif source.is_reference then
if destination_type.is_reference then
-- Reference to Reference :
Result := expression;
generic_cast(destination_type);
else
-- Reference to Expanded :
!IMPLICIT_CAST!Result.make(expression,destination_type);
end;
elseif destination_type.is_reference then
-- Expanded to Reference :
computes_for(source,destination_type);
!IMPLICIT_CAST!Result.make(expression,destination);
else
-- Expanded to Expanded :
if destination_type.is_real and then source.is_integer then
-- INTEGER to REAL :
!IMPLICIT_CAST!Result.make(expression,destination_type);
elseif destination_type.is_double then
if source.is_integer or else source.is_real then
-- INTEGER to DOUBLE or REAL to DOUBLE :
!IMPLICIT_CAST!Result.make(expression,destination_type);
else
Result := expression;
end;
elseif destination_type.is_bit then
source_bit ?= source.run_type;
destination_bit ?= destination_type.run_type;
if source_bit.nb /= destination_bit.nb then
!IMPLICIT_CAST!Result.make(expression,destination_type);
else
Result := expression;
end;
else
Result := expression;
generic_cast(destination_type);
end;
end;
ensure
Result /= Void
end;
feature {IMPLICIT_CAST}
notify(expression: EXPRESSION; source_type, destination_type: TYPE) is
-- Notify some really needed conversion of `expression' from
-- some `source_type' to some `destination_type'.
require
source_type.run_time_mark /= destination_type.run_time_mark;
source_type.is_expanded or destination_type.is_expanded
do
computes_for(source_type,destination_type);
if source_types.has(entry) then
source := source_types.at(entry);
if not source.is_a(source_type) then
eh.cancel;
source_types.put(source_type,entry);
expressions.put(expression,entry);
end;
else
if source.is_expanded then
destination.run_class.set_at_run_time;
end;
source_types.put(source_type,entry);
destination_types.put(destination_type,entry);
if expression /= Void then
expressions.put(expression,entry);
end;
-- *** To DEBUG ***
-- if true then
-- eh.append("CONVERSION_HANDLER.Notify : ");
-- eh.append(entry);
-- eh.append(" originally: from ");
-- eh.append(source_type.run_time_mark);
-- eh.append(" to ");
-- eh.append(destination_type.run_time_mark);
-- if expression /= Void then
-- eh.add_position(expression.start_position);
-- end;
-- eh.print_as_warning;
-- end;
--
end;
end;
feature {SWITCH, FORMAL_ARG_LIST, E_STRIP}
passing(source_type, destination_type: TYPE) is
do
if source_type.is_expanded then
if destination_type.is_reference then
notify(Void,source_type,destination_type);
end;
elseif destination_type.is_expanded then
notify(Void,source_type,destination_type);
else
source := source_type;
generic_cast(destination_type);
end;
end;
feature {IMPLICIT_CAST,C_PRETTY_PRINTER,E_STRIP}
c_function_call(source_type, destination_type: TYPE) is
do
computes_for(source_type,destination_type);
if source.run_time_mark /= destination.run_time_mark then
cpp.put_character('T');
cpp.put_integer(source.id);
cpp.put_string(fz_to_t);
cpp.put_integer(destination.id);
cpp.put_character('(');
else
cpp.put_string("/*NO_CONVERSION*/(");
end;
end;
feature {C_PRETTY_PRINTER}
c_definitions is
local
i: INTEGER;
do
from
i := 1;
until
i > source_types.count
loop
source := source_types.item(i);
entry := source_types.key(i);
destination := destination_types.at(entry);
computes_for(source,destination);
if source.is_bit then
c_function_definition;
elseif source.is_expanded and then destination.is_expanded then
-- Because it is worthless or already done with #define in
-- "SmallEiffel/sys/runtime/base.h".
else
c_function_definition;
end;
i := i + 1;
end;
end;
feature {SMALL_EIFFEL}
finish_falling_down is
local
i: INTEGER;
source_type, destination_type: TYPE;
rc1, rc2: RUN_CLASS;
do
from
i := 1;
until
i > source_types.count
loop
source_type := source_types.item(i);
entry := source_types.key(i);
destination_type := destination_types.at(entry);
computes_for(source_type,destination_type);
if source.is_reference then
if destination.is_expanded then
echo.put_string(entry);
echo.put_string(" (");
echo.put_string(source_type.run_time_mark);
echo.put_string(fz_to);
echo.put_string(destination_type.run_time_mark);
echo.put_string(")%N");
small_eiffel.reference_to_expanded(source_type);
end;
end;
if source.is_user_expanded then
if destination.is_reference then
rc1 := source.run_class;
rc2 := destination.run_class;
end;
elseif destination.is_user_expanded then
if source.is_reference then
rc1 := source.run_class;
rc2 := destination.run_class;
end;
end;
if rc1 /= Void then
rc1.shared_attributes(rc2);
rc2.shared_attributes(rc1);
rc1 := Void;
end;
i := i + 1;
end;
end;
feature {NONE}
source, destination: TYPE;
-- Temporary memory to store actual `source' and `destination' type.
entry: STRING;
-- Temporary memory to store the `entry' in dictionaries.
computes_for(source_type, destination_type: TYPE) is
-- Compute actual `source' and `destination' as well as the
-- corresponding `entry' used for dictionaries.
require
source_type.is_expanded or destination_type.is_expanded
do
if source_type.is_expanded then
source := source_type;
if destination_type.is_expanded then
destination := destination_type;
else
destination := source.actual_reference(destination_type);
end;
else
destination := destination_type;
source := destination.actual_reference(source_type);
end;
buffer.clear;
buffer.append(source.run_time_mark);
buffer.append(fz_to);
buffer.append(destination.run_time_mark);
entry := string_aliaser.item(buffer);
end;
source_types: DICTIONARY[TYPE,STRING] is
-- All source types available from some `entry'.
once
!!Result.make;
end;
destination_types: DICTIONARY[TYPE,STRING] is
-- All destination types available from `entry'.
once
!!Result.make;
end;
expressions: DICTIONARY[EXPRESSION,STRING] is
-- This dictionary is used to warn the user about some
-- unwanted implicit objects allocation.
-- Also use the same `entry' access key.
once
!!Result.make;
end;
c_function_definition is
-- Called to produce the C convertion function for `entry', `source'
-- and `destination'.
require
source.run_time_mark /= destination.run_time_mark
local
rc: RUN_CLASS;
do
echo.put_string("Conversion from ");
echo.put_string(entry);
echo.put_string(" in C function ");
buffer.clear;
destination.c_type_for_result_in(buffer);
buffer.extend(' ');
buffer.extend('T');
source.id.append_in(buffer);
buffer.append(fz_to_t);
destination.id.append_in(buffer);
buffer.extend('(');
source.c_type_for_argument_in(buffer)
buffer.append(" source)");
echo.put_string(buffer);
echo.put_string(fz_b6);
if destination.is_expanded then
if source.is_expanded then
-- expanded to expanded :
buffer.copy("#define T");
source.id.append_in(buffer);
buffer.append(fz_to_t);
destination.id.append_in(buffer);
buffer.append("(x) (x)%N");
cpp.put_string_on_h(buffer);
else
-- reference to expanded :
cpp.put_c_heading(buffer);
buffer.copy("return (((");
source.c_type_for_target_in(buffer);
buffer.append(")source)->_item);%N");
cpp.put_string(buffer);
cpp.put_string(fz_12);
end;
else
-- expanded to reference :
cpp.put_c_heading(buffer);
cpp.put_character('T');
cpp.put_integer(destination.id);
cpp.put_character('*');
rc := destination.run_class;
gc_handler.allocation_of("destination",rc);
if source.is_basic_eiffel_expanded then
cpp.put_string("destination->_item=source;%N");
else
cpp.put_string("memcpy((((Tid*)destination)");
if rc.is_tagged then
cpp.put_string("+1");
end;
cpp.put_string("),&source,sizeof(source));%N");
end;
cpp.put_string("return ((T0*)destination);%N}%N");
end;
end;
generic_cast(destination_type: TYPE) is
local
s_gl, d_gl: ARRAY[TYPE];
s, d: TYPE;
i, j: INTEGER;
do
if source.is_generic and then destination_type.is_generic then
s_gl := source.generic_list;
d_gl := destination_type.generic_list;
from
i := s_gl.upper;
until
i = 0
loop
from
j := d_gl.upper;
s := s_gl.item(i);
until
j = 0
loop
d := d_gl.item(j);
if d.is_a(s) then
passing(d,s);
else
eh.cancel;
end;
j := j - 1;
end;
i := i - 1;
end;
end;
end;
buffer: STRING is
once
!!Result.make(128);
end;
fz_to: STRING is " to ";
singleton_memory: CONVERSION_HANDLER is
once
Result := Current;
end;
invariant
is_real_singleton: Current = singleton_memory
end -- CONVERSION_HANDLER